package server.thread;

import server.http.*;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 * @author Sérgio C. Peres
 * @author Guilherme Alves
 */
public class HTTPResponse
{
    private HTTPServer server;
    private DataOutputStream output;
    private String addressReq;
    private boolean isNotGETRequest;
    
    protected static final DateFormat HTTP_DATE_FORMAT = new SimpleDateFormat(
            "EEE, dd MMM yyyy HH:mm:ss z");

    public HTTPResponse(HTTPServer srv, DataOutputStream output)
    {
        this.output = output;
        this.server = srv;
        this.isNotGETRequest = false;
    }

    public boolean setRequest(String request, String addressReq)
    {
        try
        {            
            if (!request.equalsIgnoreCase("GET"))
            {
                this.isNotGETRequest = true;
            }
            else
            {
                this.addressReq = addressReq;
            }
        } catch (StringIndexOutOfBoundsException e)
        {
            return false;
        }
        return true;
    }

    public void sendResponse() throws IOException
    {
        if (!this.isNotGETRequest){
            this.readFile();
        }
        else
        {
            output.writeBytes(returnHTMLError(400, null));
        }
        output.close();
    }

    public void readFile() throws IOException
    {
        FileReader in;
        try
        {
            in = new FileReader(this.server.getPathDir() + "\\" + 
                    ((this.addressReq.length() != 1) ? this.addressReq.trim().substring(1) : "index.html"));
            try
            {
                output.write(getHead("200 OK",defineTipo(addressReq.trim())).getBytes());
                   
                int i;
                for (i = in.read(); i != -1; i = in.read())
                {
                    output.writeByte(i);
                }
                in.close();
            } catch (IOException ex)
            {
                output.writeBytes(returnHTMLError(500, this.addressReq));
            }
        } catch (FileNotFoundException ex)
        {
            output.writeBytes(returnHTMLError(404, this.addressReq));
        }
    }

    private String returnHTMLError(int errorCode, String req)
    {
        String title, h1, messengerError;
        title = h1 = messengerError = "";
        String res = "";
        
        switch (errorCode)
        {
            case 404:
                res = getHead("404 Not found","text/html; charset=UTF-8");
                title = "404 Not Found";
                h1 = "Not Found";
                messengerError = "        <p>The requested URL " + req + " was not found on this server.</p>\n"
                        + "        <p>\n"
                        + "            Additionally, a 404 Not Found\n"
                        + "            terror was encountered while trying to use an ErrorDocument to handle the request.\n"
                        + "        </p>\n";
                break;
                
            case 400:
                res = getHead("400 Bad request","text/html; charset=UTF-8");
                title = "400 Bad Request";
                h1 = "Bad Request";
                break;
                
            default:
                res = getHead("500 Internal Server Error","text/html; charset=UTF-8");
                title = "500 Internal Server Error";
                h1 = "Internal Server Error";
                break;
        }
        
        res += "<!DOCTYPE html>\n"
                + "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
                + "    <head>\n"
                + "        <title>" + title + "</title>\n"
                + "    </head>\n"
                + "    <body>\n"
                + "        <h1>" + h1 + "</h1>\n"
                + "        <!-- Messenger error! -->\n\n"
                + messengerError
                + "\n\n        <!-- Fim messenger error -->\n"
                + "        <hr />\n"
                + "        <address>Web Server at " + "" + " Port " + this.server.getPort() + "</address>\n"
                + "    </body>\n"
                + "</html>";
        return res;
    }
    
    private String getHead(String codErro,String tipoRequisicao) {
        // Head
        StringBuilder sb = new StringBuilder();
        // Cria primeira linha do status code, no caso 200 OK
        sb.append("HTTP/1.1 " + codErro).append("\r\n");

        // Cria os cabeçalhos
        sb.append("Date: ").append(HTTP_DATE_FORMAT.format(new Date()))
                .append("\r\n");
        sb.append("Server: Web Server")
                .append("\r\n");
        sb.append("Connection: Close").append("\r\n");
        sb.append("Content-Type: " + tipoRequisicao).append("\r\n");
        sb.append("\r\n");
        return sb.toString();
    }
    
    private String defineTipo(String file) {
        /**
         * Mais tipo acesse em:
         * http://en.wikipedia.org/wiki/MIME_type#List_of_common_media_subtype_prefixes
         */
        String tipo = "";
        int i = (file.length() - 1);
        for ( ; i > 0;  i--) {
            if (file.charAt(i) == '.') {
                break;
            }
        }
        
        System.out.println("»»» Tipo do arquivo requisitado: "+file.substring(i));
        switch(file.substring(i)) {
            // tipo de Arquivos
            case ".http": tipo = "text/html; charset=UTF-8"; break;
            case ".css" : tipo = "text/css; charset=UTF-8"; break;
            case ".js" : tipo = "text/javascript; charset=UTF-8"; break;
            // tipos de Imagens
            case ".gif": tipo = "image/gif;"; break;
            case ".jpg" : tipo = "image/jpeg;"; break;
            case ".jpeg" : tipo = "image/jpeg;"; break;
            case ".png": tipo = "image/png"; break;
            
            default: tipo = "text/html; charset=UTF-8";
        }
        return tipo;
    }
}